package com.globalwave.common.scheduling;

import java.util.Date;
import java.util.concurrent.TimeUnit;

import org.springframework.scheduling.Trigger;
import org.springframework.scheduling.TriggerContext;

public class OneTimeTrigger implements Trigger {


	private final TimeUnit timeUnit;

	private volatile long initialDelay = 0;


	/**
	 * Create a trigger with the given period in milliseconds.
	 */
	public OneTimeTrigger(long initialDelay) {
		this(initialDelay, null);
	}

	/**
	 * Create a trigger with the given period and time unit. The time unit will
	 * apply not only to the period but also to any 'initialDelay' value, if
	 * configured on this Trigger later via {@link #setInitialDelay(long)}.
	 */
	public OneTimeTrigger(long initialDelay, TimeUnit timeUnit) {
		this.timeUnit = (timeUnit != null) ? timeUnit : TimeUnit.MILLISECONDS;
		this.initialDelay = this.timeUnit.toMillis(initialDelay);
	}


	/**
	 * Specify the delay for the initial execution. It will be evaluated in
	 * terms of this trigger's {@link TimeUnit}. If no time unit was explicitly
	 * provided upon instantiation, the default is milliseconds. 
	 */
	public void setInitialDelay(long initialDelay) {
		this.initialDelay = this.timeUnit.toMillis(initialDelay);
	}


	/**
	 * Returns the time after which a task should run again.
	 */
	public Date nextExecutionTime(TriggerContext triggerContext) {
		if (triggerContext.lastScheduledExecutionTime() == null) {
			return new Date(System.currentTimeMillis() + this.initialDelay);
		}
		else {
			return null ;
		}
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj) {
			return true;
		}
		if (!(obj instanceof OneTimeTrigger)) {
			return false;
		}
		OneTimeTrigger other = (OneTimeTrigger) obj;
		return this.initialDelay == other.initialDelay;
	}

	@Override
	public int hashCode() {
		return (int)(41 * this.initialDelay); 
	}

}
